package com.payment.service.impl;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.payment.common.Aliconfig.AlipayConfig;
import com.payment.common.utils.DateUtils;
import com.payment.common.utils.LocalDateTimeUtils;
import com.payment.common.wxutils.*;
import com.payment.entity.po.PayOrder;
import com.payment.mapper.PayOrderMapper;
import com.payment.service.TrainingService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 *
 */
@Slf4j
@Service("TrainingService")
public class TrainingServiceImpl implements TrainingService {
	@Resource
	private AlipayConfig alipayConfig;
	@Resource
	private WxConfigUtil wxConfigUtil;
	@Resource
	private PayOrderMapper payOrderMapper;
	private static final Logger logger = LoggerFactory.getLogger(TrainingServiceImpl.class);
	@Override
	@Retryable(value = Exception.class,maxAttempts = 6,backoff = @Backoff(delay = 5000,multiplier = 1.0))
	public int  payTraining(String outTradeNo,String paytype) throws Exception {
		QueryWrapper<PayOrder> wrapper = new QueryWrapper();
		wrapper.eq("out_trade_no", outTradeNo);
		PayOrder payOrder = payOrderMapper.selectOne(wrapper);
		System.out.println("进入定时轮训"+new Date());
		if("1".equals(paytype)){
			AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getGateWayUrl(),
					alipayConfig.getAppId(),
					alipayConfig.getAliPayPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
					alipayConfig.getAliPayPublicKey(),
					alipayConfig.getSignType());
			AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
			request.setBizContent ( "{"   +
					"\"out_trade_no\":\""+outTradeNo+"\","   +
					"\"trade_no\":\"\"}" );  //设置业务参数
			AlipayTradeQueryResponse response = alipayClient.execute(request);
			PayOrder payOrder1 = new PayOrder();
			payOrder1.setId(payOrder.getId());
			payOrder1.setTradeNo(response.getTradeNo());
			payOrder1.setSubMessage(response.getSubMsg());
			payOrder1.setSubCode(response.getSubCode());
			payOrder1.setCode(response.getCode());
			payOrder1.setMessage(response.getMsg());
			payOrder1.setBuyerId(response.getBuyerUserId());
			payOrder1.setTradeStatus(response.getTradeStatus());
			payOrder1.setTotalAmount(new BigDecimal(response.getBuyerPayAmount()));
			payOrder1.setGmtPayment(LocalDateTimeUtils.convertDateToLDT(response.getSendPayDate()));
			System.out.println("payOrder1============="+payOrder1);
			// todo  为什么修改无效
			int i = payOrderMapper.updateById(payOrder1);
			System.out.println("i+==========="+i);
			if(response.isSuccess()){
				logger.debug("code:"+response.getCode());
				if("10000".equals(response.getCode())){
					if("TRADE_SUCCESS".equals(response.getTradeStatus())){
						System.out.println("status:"+response.getTradeStatus());
						PayOrder payOrder2 = new PayOrder(payOrder.getId(),null,null,null,null,null,null,null,null,response.getTradeNo(),null,null,response.getSubMsg(),response.getSubCode(),response.getCode(),response.getMsg(),null,response.getTradeNo(),alipayConfig.getAppId(),null,response.getBuyerUserId(),response.getTradeStatus(),new BigDecimal(response.getBuyerPayAmount()), null,LocalDateTimeUtils.convertDateToLDT(response.getSendPayDate()),null,null,null,1,null,null);
						payOrderMapper.updateById(payOrder2);
						return 200;
					}else if("WAIT_BUYER_PAY".equals(response.getTradeStatus())){
						logger.debug("status:"+response.getTradeStatus());

						throw new Exception("订单创建中继续轮训！");
					}else if("TRADE_CLOSED".equals(response.getTradeStatus())){
						logger.debug("未付款交易超时关闭，或支付完成后全额退款");
						logger.debug("status:"+response.getTradeStatus());
						return  500;
					}else {
						logger.debug("status:"+response.getTradeStatus());
						return 200;
					}
				}else if("40004".equals(response.getCode())) {
					if("ACQ.SYSTEM_ERROR".equals(response.getSubCode())){
						log.debug("系统错误,重新发起请求");
						throw new Exception("系统错误,重新发起请求");
					}else if("ACQ.INVALID_PARAMETER".equals(response.getSubCode())){
						log.debug("参数无效");
						return 501;
					}else {
						System.out.println("code = " + response.getCode());
						throw new Exception("查询的交易不存在！");
					}
				}else{
					log.debug("系统错误,重新发起请求");
					return  500;
				}
			} else {
				System.out.println("subCode为空");
				return 500;
			}
		}else{
			logger.debug("进入查询微信订单接口");
			SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
			packageParams.put("appid", wxConfigUtil.getAPP_ID());// 公众账号ID
			packageParams.put("mch_id", wxConfigUtil.getMCH_ID());// 商户号*/
			packageParams.put("nonce_str", WxConfigUtil.getNoncestr());
			packageParams.put("out_trade_no", outTradeNo);// 商户订单号
			String sign = PayCommonUtil.createSign("UTF-8", packageParams,
					wxConfigUtil.getAPI_KEY());
			packageParams.put("sign", sign);// 签名
			String requestXML = PayCommonUtil.getRequestXml(packageParams);
			//调微信统一下单接口
			String resXml = HttpUtil.postData(WxConfigUtil.CHECK_ORDER_URL, requestXML);
			Map map = XMLUtil.doXMLParse(resXml);
			String returnCode = (String) map.get("return_code");
			String returnMsg = (String) map.get("return_msg");
			if ("SUCCESS".equals(returnCode)) {
				//调用成功
				String resultCode = (String) map.get("result_code");
				String errCodeDes = (String) map.get("err_code_des");
				if ("SUCCESS".equals(resultCode)) {
					String returnTradeState = (String) map.get("trade_state");
					if ("SUCCESS".equals(returnTradeState)) {
						logger.info("查询订单已经缴费", outTradeNo, DateUtils.formatDateTime(new Date()));
						PayOrder payOrder1 = new PayOrder();
						payOrder1.setId(payOrder.getId());
						payOrder1.setCode(returnCode);
						payOrder1.setMessage(returnMsg);
						payOrder1.setPayStatus(1);
						payOrder1.setTradeNo((String) map.get("transaction_id"));
						String payTime = (String) map.get("time_end");
						DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
						payOrder1.setGmtPayment(LocalDateTime.parse(payTime,df));
						payOrderMapper.updateById(payOrder1);
						return 200;
					}else if("USERPAYING".equals(returnTradeState)){
						logger.error("订单号:{}错误信息:{}", outTradeNo, errCodeDes);
						System.out.println("1111111111111111111111111");
						throw new Exception("用户支付中，需要输入密码");
					}
					logger.error("订单号:{}错误信息:{}", outTradeNo, errCodeDes);
					return 500;
				} else {
					logger.error("订单号:{}错误信息:{}", outTradeNo, errCodeDes);
					return 500;
				}
			} else {
				logger.error("订单号:{}错误信息:{}", outTradeNo, returnMsg);
				return 500;
			}
	}
	}
	@Recover
	public int recover(Exception e,String outTradeNo,String paytype) throws Exception {
		System.out.println("进入关闭订单方法"+new Date());
		QueryWrapper<PayOrder> wrapper = new QueryWrapper();
		wrapper.eq("out_trade_no", outTradeNo);
		PayOrder payOrder = payOrderMapper.selectOne(wrapper);
		if("1".equals(paytype)){
			AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getGateWayUrl(),
					alipayConfig.getAppId(),
					alipayConfig.getAliPayPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
					alipayConfig.getPublicKey(),
					alipayConfig.getSignType());
			AlipayTradeCancelRequest request = new AlipayTradeCancelRequest ();
			request.setBizContent("{" +
					"\"out_trade_no\":\""+outTradeNo+"\"," +
					"\"trade_no\":\"\"" +
					"  }");
			AlipayTradeCancelResponse response = alipayClient.execute(request);
			payOrder.setTradeStatus(response.getAction());
			payOrder.setCode(response.getCode());
			payOrder.setSubCode(response.getSubCode());
			payOrder.setSubMessage(response.getSubMsg());
			payOrderMapper.updateById(payOrder);
			if(response.isSuccess()){
				if("10000".equals(response.getCode())){
					logger.debug("code:" + response.getCode());
					if("close".equals(response.getAction())){
						return 201;
					}else if("refund".equals(response.getAction())){
						return 201;
					}
					return 500;
				}else{
					if ("ACQ.TRADE_HAS_SUCCESS".equals(response.getSubCode())) {
						logger.debug("撤销订单成功");
						return 201;
					}else if("AQC.SYSTEM_ERROR".equals(response.getSubCode())){
						logger.debug("系统错误请使用相同的参数再次调用");
						return 501;
					}else if("ACQ.SELLER_BALANCE_NOT_ENOUGH".equals(response.getSubCode())){
						logger.debug("商户的支付宝账户中无足够的资金进行撤销");
						return 501;
					}else{
						logger.debug("请查看支付宝具体业务错误码判断错误！");
						return 501;
					}
				}
			} else {
				System.out.println("调用失败"+response);
				return 501;
			}
		}else{
			SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
			packageParams.put("appid", wxConfigUtil.getAPP_ID());// 公众账号ID
			packageParams.put("mch_id", wxConfigUtil.getMCH_ID());// 商户号*/
			packageParams.put("nonce_str", WxConfigUtil.getNoncestr());
			packageParams.put("out_trade_no", outTradeNo);// 商户订单号
			String sign = PayCommonUtil.createSign("UTF-8", packageParams,
					wxConfigUtil.getAPI_KEY());
			packageParams.put("sign", sign);// 签名
			String requestXML = PayCommonUtil.getRequestXml(packageParams);
			//调微信撤销接口@TODO 修改双向证书路径
			String resXml = ClientCustomSSL.doRefund("https://api.mch.weixin.qq.com/secapi/pay/reverse", requestXML,wxConfigUtil.getMCH_ID(),wxConfigUtil.getCERT_PATH());
			Map<String,Object> map = XMLUtil.doXMLParse(resXml);
			logger.debug("撤销订单map：" + map);
			String returnCode = (String) map.get("return_code");
			String returnMsg = (String) map.get("return_msg");
			log.debug("调用信息 returnCode：" + returnCode);
			log.debug("调用信息 retrrnMsg:" + returnMsg );
			if ("SUCCESS".equals(returnCode)) {
				//调用成功
				String resultCode = (String) map.get("result_code");
				String errCodeDes = (String) map.get("err_code_des");
				if ("SUCCESS".equals(resultCode)) {
					logger.info("订单已经撤销", outTradeNo, DateUtils.formatDateTime(new Date()));
					return 201;
				} else {
					logger.error("订单号:{}错误信息:{}", outTradeNo, errCodeDes);
					return 500;
				}
			} else {
				logger.error("订单号:{}错误信息:{}", outTradeNo, returnMsg);
				return 500;
			}
		}
	}
}
